package backend;
/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

import java.util.ArrayList;

/**
 *
 * @author Christian Janke, Simon Huneck
 */
public class WeightedGraph {
   
    /**
     * 
     * @param knoten Liste aller Knoten
     * @param routen Liste aller Routen
     * @param kanten liste aller Kanten
     */
    private ArrayList<MapNode> knoten = new ArrayList<MapNode>();
    private ArrayList<MapWay> routen = new ArrayList<MapWay>();
    private ArrayList<MapEdge> kanten = new ArrayList<MapEdge>();
    
    /**
     * 
     * @param nKnoten alle Knoten
     * @param nRouten alle Ways
     */
    public WeightedGraph(ArrayList<MapWay> nRouten){
        this.routen = nRouten;
        
//////// Durchgehen aller Routen ///////////////////////////////////////////////
        for (MapWay w: this.routen){
            String name = w.getTag("name")==null ? "unbekannte Strasse" : w.getTag("name");
            ArrayList<Integer> tmpNodes = w.getNd();
//////// Durchgehen aller Verbindungen jeder Route und hinzufuegen jeder Kante /
            for (int k=0; k < tmpNodes.size()-1; k++){
                if (k == 0){
                    this.addKnoten(w.getNodes().get(k));
                }
                this.addKnoten(w.getNodes().get(k+1));
                MapNode no1 = this.getNodeByND(tmpNodes.get(k));
                MapNode no2 = this.getNodeByND(tmpNodes.get(k+1));
                double length = Punkt.dist(no1.getKoords(), no2.getKoords());
                String speedText = w.getTag("maxspeed");
                double speed = 50;
                speed = speed / 3.6; // Umrechnung in m/s
                if (speedText != null){
                    speed = Double.parseDouble(speedText);
                }
                this.kanten.add(new MapEdge(no1, no2, length, speed, name));
                if (w.getTag("oneway") == null){
                    this.kanten.add(new MapEdge(no2, no1, length, speed, name));     
                }
            }
        }
    }
    
    private void addKnoten(MapNode n){
        if (this.knoten.contains(n) == false) this.knoten.add(n);
    }
    
    /**
     * 
     * @param nd Node fuer den ND gesucht wird
     * @return ND von gesuchten node
     */
    public MapNode getNodeByND(int nd){
        MapNode back = null;
        for (int i = 0; i < this.knoten.size(); i++){
            if (this.knoten.get(i).getId() == nd) back = this.knoten.get(i);
        }
        return back;
    }
    
    /**
     * 
     * @param a Node1
     * @param b Node2
     * @return Gewicht der Kante von Node1 zu Node2
     */
    public double getLengthByNodes(MapNode a, MapNode b){
        double result = -1;
        for (MapEdge t: this.kanten){
            if ((t.getNode1() == a) && (t.getNode2() == b)) result = t.getLength();
            if ((t.getNode2() == a) && (t.getNode1() == b)) result = t.getLength();
        }
        return result;
    }
    public double getTimeByNodes(MapNode a, MapNode b){
        double result = -1;
        for (MapEdge t: this.kanten){
            if ((t.getNode1() == a) && (t.getNode2() == b)) result = t.getTime();
            if ((t.getNode2() == a) && (t.getNode1() == b)) result = t.getTime();
        }
        return result;
    }
    
    /**
     * 
     * @return Zahl der Knoten
     */
    public int getNumVertices(){
        return this.knoten.size();
    }
    
    /**
     * 
     * @param n gewuenschter Node   
     * @return alle Nachbar Nodes von n
     */
    public ArrayList<MapNode> getNeighbours(MapNode n){
        ArrayList<MapNode> result = new ArrayList<MapNode>();
        for (MapEdge kante: this.kanten){
            if (kante.getNode1() == n) result.add(kante.getNode2());
        }
        return result;
    }
    
    /**
     * 
     * @return is klar
     */
    public ArrayList<MapNode> getKnoten(){
        return this.knoten;
    }
    
    /**
     * 
     * @return is klar
     */
    public ArrayList<MapEdge> getKanten(){
        return this.kanten;
    }
    
    /**Nur zum Spass
     * 
     */
    public void printKanten(){
        for (int i=0; i < this.kanten.size(); i++){
            System.out.println(this.kanten.get(i).getNode1().toString() + " ist verbunden mit " + this.kanten.get(i).getNode2().toString() + ", hat das Laenge: " + this.kanten.get(i).getLength() + ", hat die Geschwindigkeit: " + this.kanten.get(i).getSpeed() + " und liegt auf: " + this.kanten.get(i).getName());
        }
    }
}

